package se.topshelf.golftracker.core.domain;

import org.hibernate.annotations.Sort;
import org.hibernate.annotations.SortType;
import org.hibernate.validator.constraints.Range;

import javax.persistence.*;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.text.MessageFormat;
import java.util.SortedSet;
import java.util.TreeSet;

/**
 *
 */
@Entity
@Table(name = "Hole")
public class Hole extends BaseEntity implements Comparable<Hole>{
    @NotNull
    @ManyToOne(
        cascade={CascadeType.PERSIST},
        targetEntity=Course.class
    )
    @JoinColumn(name="courseId")
    private Course course;

    @NotNull
    @Min(1)
    private Integer slopeIndex;
    @NotNull
    @Min(1)
    private Integer orderOnCourse;

    @Range(min = 3, max = 7)
    private Integer par;

    private String name = "";

    private String description;


    @OneToMany(mappedBy = "hole")
    @Sort(type = SortType.NATURAL)
    private SortedSet<TeeBox> teeBoxes = new TreeSet<TeeBox>();

    public Hole() {
    }

    public Hole(Integer orderOnCourse, Integer slopeIndex, Integer par) {
        this.orderOnCourse = orderOnCourse;
        this.slopeIndex = slopeIndex;
        this.par = par;
    }

    public Course getCourse() {
        return course;
    }

    public void setCourse(Course course) {
        this.course = course;
    }

    public Integer getSlopeIndex() {
        return slopeIndex;
    }

    public void setSlopeIndex(Integer slopeIndex) {
        this.slopeIndex = slopeIndex;
    }

    public Integer getOrderOnCourse() {
        return orderOnCourse;
    }

    public void setOrderOnCourse(Integer orderOnCourse) {
        this.orderOnCourse = orderOnCourse;
    }

    public Integer getPar() {
        return par;
    }

    public void setPar(Integer par) {
        this.par = par;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public SortedSet<TeeBox> getTeeBoxes() {
        return teeBoxes;
    }

    public void addTeeBox(TeeBox teeBox){
       assertNotAlreadyAdded(teeBox, teeBoxes);
        teeBox.setHole(this);
        teeBoxes.add(teeBox);
    }

    void setTeeBoxes(SortedSet<TeeBox> teeBoxes) {
        this.teeBoxes = teeBoxes;
    }

    @Override
    public String getGuiDescription() {
        return MessageFormat.format("{0} (index {1}, par {2})", orderOnCourse, slopeIndex, par);
    }

    public int compareTo(Hole o) {
         return orderOnCourse.compareTo(o.getOrderOnCourse());
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Hole hole = (Hole) o;

        if (!orderOnCourse.equals(hole.orderOnCourse)) return false;

        return true;
    }

    @Override
    public int hashCode() {
        return orderOnCourse.hashCode();
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        sb.append("Hole");
        sb.append("{slopeIndex=").append(slopeIndex);
        sb.append(", orderOnCourse=").append(orderOnCourse);
        sb.append(", par=").append(par);
        sb.append(", name='").append(name).append('\'');
        sb.append('}');
        return sb.toString();
    }
}
